/**
 *  @file  NetCommon.h version 1.0 2007-11-20 $
 *  @brief Including necessary network header files for different platforms.
 *  Copyright (c) 2007 by @author Zhao Jun <abitfree@gmail.com>
 */

#ifndef __NET_COMMON_H__
#define __NET_COMMON_H__

#include <iostream>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <limits>

#ifdef WIN32
#define WIN32_LEAN_AND_MEAN		// to remove the unused content from Windows.h
#include <Winsock2.h>
#include <windows.h>
#else
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/msg.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <dlfcn.h>
#include <errno.h>
#include <setjmp.h>
#include <netdb.h>
#endif


namespace vs {

/**
@brief Namespace for Network communication classes.
*/
namespace net {

/// Define the INLINE macro.
#ifdef VS_NO_INLINE
#define INLINE 
#else
#define INLINE inline
#endif

#ifdef WIN32
/**
@brief Define the socket length data type, it varies from platforms.
When compiling, any of the macros WIN32/__OS_HP_UNIX/__OS_LINUX/__OS_IBM_AIX/__OS_SOLARIS needs to be defined.
*/
typedef int SOCKETLEN_T;

/// Define the socket handle in different platforms.
typedef SOCKET SOCKET_HANDLE;

/// Define the invalid socket handle value.
const SOCKET_HANDLE INVALID_SOCKET_HANDLE = INVALID_SOCKET;

#else
typedef int SOCKET_HANDLE;
const SOCKET_HANDLE INVALID_SOCKET_HANDLE = -1;

#ifdef __OS_HP_UNIX
typedef int SOCKETLEN_T;
#endif // __OS_HP_UNIX

#ifdef __OS_LINUX
typedef socklen_t SOCKETLEN_T;
#endif //__OS_LINUX

#ifdef __OS_IBM_AIX
typedef unsigned int SOCKETLEN_T;
#endif // __OS_IBM_AIX

#ifdef __OS_SOLARIS
typedef int SOCKETLEN_T;
#endif // __OS_SOLARIS

#define SOCKET_ERROR -1
#endif


/// Wrapper for the error information.
INLINE
int GetNetError()
{
#ifdef WIN32
	return WSAGetLastError();
#else
	return errno;
#endif
}

/// Call this function for initializing before using net lib.
INLINE
int StartupNetwork(int version)
{
#ifdef WIN32
	WSADATA  ws;
	if ( WSAStartup(version, &ws) != 0 )
	{
		WSACleanup();
		return -1;
	}
#endif
	return 0;
}

/// Call this function to cleanup net lib.
INLINE
int CleanupNetwork()
{
#ifdef WIN32
	WSACleanup();
#endif
	return 0;
}

/// Wrapper class for net lib initializing and cleanup.
class NetInitializer
{
public:
	/// Default constructor, initialize the net lib.
	NetInitializer(int version)
	{
		error_code_ = StartupNetwork(version);
	}

	/// Destructor, cleanup the net lib.
	~NetInitializer()
	{
		CleanupNetwork();
	}

	/// Return the status of network initialization.
	bool IsNetworkReady() const
	{
		return error_code_ == 0;
	}

private:
	// Save the status of the network initialization.
	int error_code_;
};

// for debug
#define net_debug printf

}	// namespace net
}	// namespace vs

#endif	// __NET_COMMON_H__
